with Legend.Traces;
with Legend.Settings;
with Legend.Colors;
with Ada.Strings; use Ada.Strings;
package body Legend.Dialogs is

   procedure Prompt (
      this : in out Dialog_Type;
      Value : UTF8_String
      )
   is
   begin
      Set_Unbounded_String(this.F_Prompt, Value);
      this.Canvas.Invalidate;
   end Prompt;

   function Prompt (
      this : Dialog_Type
      ) return UTF8_String
   is
   begin
      return To_String(this.F_Prompt);
   end Prompt;

   procedure Linefeed (
      this  : in out Dialog_Type;
      Value : UTF8_String
      )
   is
   begin
      Set_Unbounded_String(this.F_Linefeed, Value);
   end Linefeed;

   function Linefeed (
      this : Dialog_Type
      ) return UTF8_String
   is
   begin
      return To_String(this.F_Linefeed);
   end Linefeed;

   procedure Icon (
      this  : in out Dialog_Type;
      Value : Picture_Type
      )
   is
   begin
      this.F_Icon.Surface := Value.Surface;
   end Icon;

   procedure Paint (this : in out Dialog_Type)
   is
      use Interfaces.C;

      em             : constant double := double(Settings.Dialog.Font.Size);
      padding_left   : constant double := 2.0 * em;
      padding_right  : constant double := 2.0 * em;
      padding_top    : constant double := 2.0 * em;
      padding_bottom : constant double := 2.0 * em;

      brush : Cairo.Context.Cairo_Context_Ref;
      R : array(1..3) of SDL.Video.Rect_t := (others => (0, 0, 0, 0));
      -- 1 => Prompt, 2 => Icon, 3 => Prompt + Icon
      Max_Length : Natural := 12;
      Line_Count : Natural := 0;
      dx : double := padding_left;
      dy : double := padding_top + em;

      package Lines is
         new String_Utils.Generic_Split_Reader(this.Prompt, this.Linefeed);
   begin
      Lines.Reset;
      while Lines.Next loop
         Max_Length := Natural'Max(Max_Length, UTF8_Length(Lines.Piece));
         Line_Count := Line_Count + 1;
      end loop;
      R(1).H := Uint16_t(double(Line_Count) * em * 3.0/2.0 + padding_top + padding_bottom);
      R(1).W := Uint16_t(double(Max_Length) * em + padding_left + padding_right);
      R(3).X := (Int16_t(SDL.Video.Get_Video_Surface.W) - Int16_t(R(1).W)) / 2;
      R(3).Y := (Int16_t(SDL.Video.Get_Video_Surface.H) - Int16_t(R(1).H)) / 2;
      if this.F_Icon.Surface /= null then
         R(2).X := Int16_t(R(1).W) + 5;
         R(2).W := Uint16_t(this.F_Icon.Surface.W) + 8;
         R(2).H := Uint16_t(this.F_Icon.Surface.H) + 8;
         R(3).W := R(1).W + R(2).W + 5;
         R(3).H := Uint16_t'Max(R(1).H, R(2).H);
      else
         R(3).W := R(1).W;
         R(3).H := R(1).H;
      end if;
      this.Canvas.Bind(Region => R(3), Save_Region => True);
      brush := this.Canvas.As_Brush;
      this.Canvas.Clear((A => 128, others => 0));
      -- this.Canvas.Draw_Border;
      this.Canvas.Draw_Round_Rect(R(1), Fore_Color => Colors.White, Groove => False);
      this.Canvas.Set_True_Font(Unbounded.To_String(Settings.Dialog.Font.Name));
      brush.Set_Font_Size(em);
      this.Canvas.Set_Brush_Color(Colors.Yellow);
      Lines.Reset;
      while Lines.Next loop
--         Trace_Log(" : " & Lines.Piece);
         brush.Move_To(dx, dy);
         brush.Show_Text(Lines.Piece);
         dy := dy + 1.5 * double(em);
      end loop;
      brush.Stroke;
      if this.F_Icon.Surface /= null then
         this.Canvas.Draw_Round_Rect(
            R(2), 
            Back_Color => (B => 255, others => 128),
            Fore_Color => Colors.White,
            Groove     => False);
         this.Canvas.Accept_Brush_Changed;
         this.Canvas.Draw_Picture(this.F_Icon, (R(2).X + 2, R(2).Y + 2));
         this.Canvas.Accept_SDL_Changed;
      else
         this.Canvas.Accept_Brush_Changed;
      end if;
   end Paint;

   procedure On_Key_Up (
      this          : in out Dialog_Type;
      Message       : SDL.Events.Keyboard_Event_t;
      Cancel_Bubble : in out Boolean
      )
   is
   begin
      Cancel_Bubble := True;
      if not this.F_Expect.Is_Empty then
         if not this.F_Expect.Contains(Message.Keysym.Sym) then
            return;
         end if;
      end if;
      this.F_Result := message.Keysym.Sym;
      this.Close;
   end On_Key_Up;

   procedure Add_Expect (
      this  : in out Dialog_Type;
      Key   : SDL.Keysym.Key_t
      )
   is
   begin
      this.F_Expect.Include(Key);
   end Add_Expect;

   procedure Clear_Expect (this : in out Dialog_Type)
   is
   begin
      this.F_Expect.Clear;
   end Clear_Expect;

   function Dialog_Result (this : Dialog_Type) return SDL.Keysym.Key_t
   is
   begin
      return this.F_Result;
   end Dialog_Result;

   procedure Initialize (this : in out Dialog_Type)
   is
   begin
      Append(this.F_Linefeed, AscII.LF);
      this.F_Icon := (Position => (0, 0), Surface => null);
   end Initialize;


end Legend.Dialogs;
